package jp.co.jalinfotec.sxt.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;

import jp.co.jalinfotec.sxt.common.PMF;
import jp.co.jalinfotec.sxt.dto.OrderDto;
import jp.co.jalinfotec.sxt.entity.OrderEntity;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;

import com.google.appengine.api.datastore.Key;

@Service("OrderService")
public class OrderServiceImpl implements OrderService {

	/** Logging  */
	private static final Log log = LogFactory.getLog(OrderServiceImpl.class);
	
	/**
	 * Store order info.<br />
	 * When order exists, order info will be updated.
	 * @param bean Order info.
	 * @return on success, return true
	 */
	@Override
	public boolean store(OrderDto dto){
		
		// When parameter is wrong, return false
		if (dto.getUserId().equals(null)) return false;
				
		// when order exists, update.
		if (this.exist(dto.getUserId(), dto.getTargetDate())){
			PersistenceManager pm =	PMF.get().getPersistenceManager();
			try{
				// Create Key
				Key key = OrderEntity.createKey(dto.getUserId(), dto.getTargetDate());
				// Get Entity
				OrderEntity storedEntity = pm.getObjectById(OrderEntity.class, key);
				// Set updating values
				storedEntity.setType(dto.getType());
				// Store
				pm.makePersistent(storedEntity);
			}catch(Exception ex){
				log.info(String.format("ID={0}, note={1}", dto.getUserId(), "updateOfOrder"));
				return false;
			}finally{
				pm.close();
			}
			return true;
		}
		
		// when user doesn't exist, register
		PersistenceManager pm =	PMF.get().getPersistenceManager();
		try{
			// Create Entity
			OrderEntity storingEntity = new OrderEntity();
			storingEntity.setUserId(dto.getUserId());
			storingEntity.setTitle(dto.getTitle());
			storingEntity.setType(dto.getType());
			storingEntity.setTargetDate(new Date());
			// Create And Set Key
			storingEntity.setInternalKey(OrderEntity.createKey(dto.getUserId(), new Date()));
			// Store
			pm.makePersistent(storingEntity);
		}catch(Exception ex){
			log.info(String.format("ID={0}, note={1}", dto.getUserId(), "registerOfOrder"));
			return false;
		}finally{
			pm.close();
		}	
		return true;
	}
	
	/**
	 * Delete order info.
	 * @param bean Order info.
	 * @return on success, return true.
	 */
	public boolean delete(OrderDto dto){
		// When not exists, return false.
		if(!this.exist(dto.getUserId(), dto.getTargetDate())) return false;
		
		PersistenceManager pm =	PMF.get().getPersistenceManager();
		try{
			// Create Key
			Key key = OrderEntity.createKey(dto.getUserId(), dto.getTargetDate());
			// Get Entity
			OrderEntity storedEntity = pm.getObjectById(OrderEntity.class, key);
			// Delete
			pm.deletePersistent(storedEntity);
		}catch(Exception ex){
			log.info(String.format("ID={0}, note={1}", dto.getUserId(), "deleteOfOrder"));
			return false;
		}finally{
			pm.close();
		}
		return true;
	}
	
	/**
	 * Get order info.
	 * @param id Order ID
	 * @param date Target Date
	 * @return Order info.
	 */
	public OrderDto get(String id, Date date){
		OrderEntity orderEntity = null;
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try{
			// Create Key
			Key key = OrderEntity.createKey(id, date);
			// Get Entity
			orderEntity = pm.getObjectById(OrderEntity.class, key);
		}catch(Exception ex){
			log.info(String.format("ID={0}, note={1}", id, "getOfOrder"));
			return null;
		}finally{
			pm.close();
		}
		return new OrderDto(orderEntity.getUserId(),
							orderEntity.getTitle(),
							orderEntity.getType());
	}
	
	/**
	 * Get list of orders.
	 * @param date Target Date
	 * @return list of orders.
	 */
	@SuppressWarnings("unchecked")
	public List<OrderDto> getAll(Date date){
		List<OrderDto> orders = new ArrayList<OrderDto>();
		PersistenceManager pm = PMF.get().getPersistenceManager();
		// Generate Query
		Query query = pm.newQuery(OrderEntity.class);
		// TODO adding 
		query.setOrdering("userId asc");
		try{
			// Get All
			List<OrderEntity> list = (List<OrderEntity>)query.execute();
			for(OrderEntity entity : list) 
				orders.add(new OrderDto(entity.getUserId(),
										entity.getTitle(),
										entity.getType()));
		}catch(Exception ex){
			log.info(String.format("ID={0}, note={1}", "(none)", "getAllOfOrder"));
			return null;
		}finally{
			query.closeAll();
			pm.close();
		}
		return orders;
	}
	
	/**
	 * Check if the specified order exists.
	 * @param id UserID
	 * @param date Target Date
	 * @return when exists, return true.
	 */
	public boolean exist(String id, Date date){
		// Get All Users
		List<OrderDto> list = this.getAll(date);
		
		// Check if the user who has the specified id exists.
		for(OrderDto dto : list){
			if(dto.getUserId().equals(id) && dto.getTargetDate().equals(date)) return true;
		}
		return false;
	}
}